<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Libs\Pools;

use Srv\Libs\Common\CommJson;
use Srv\Libs\ConfModel\DbConf;
use Srv\Libs\Exception\MysqlConnectException;
use Srv\Libs\Exception\MysqlPoolException;
use Srv\Libs\Exception\PoolItemException;
use Srv\Libs\Exception\PoolItemMysqlException;
use Srv\Libs\Frame\Logs;
use Srv\Libs\Storage\DataMysql;

final class PoolDb extends PoolAbstract
{
    private ?DbConf $DbConf                     = null;         // DbConf

    /**
     * PoolDb constructor.
     * @param DbConf $DbConf
     * @throws MysqlPoolException
     * __construct
     */
    final public function __construct(DbConf $DbConf)
    {
        $this->checkTime        = max($DbConf->getPoolCheckTime(), 0);
        $this->recycleTime      = $DbConf->getPoolRecycleTime();
        $this->waitMilliTime    = $DbConf->getPoolWaitMilliTime();
        $this->startNum         = $DbConf->getPoolStartNum();
        $this->minNum           = $DbConf->getPoolMinNum();
        $this->maxNum           = $DbConf->getPoolMaxNum();
        $this->DbConf           = $DbConf;
        $this->DbConf->setKeepalive(false);     // 使用短连接
        if($this->minNum > $this->startNum || $this->startNum > $this->maxNum || $this->startNum < 1 || $this->minNum < 1 || $this->maxNum < 1){
            throw new MysqlPoolException(CommJson::encodeArray(['msg' => 'Configure failed', 'groupName' => $this->DbConf->getGroupName(), 'startNum' => $this->startNum, 'minNum' => $this->minNum, 'maxNum' => $this->maxNum]), -1);
        }
        parent::__construct(Pool::getIndexKey(Pool::POOL_DB, $this->DbConf->getGroupName()));
    }

    /**
     * __destruct
     */
    final public function __destruct()
    {
        parent::__destruct();
    }

    /**
     * @param bool $isUse
     * @return bool|PoolItem
     * getNewPoolItem
     */
    final protected function getNewPoolItem(bool $isUse)
    {
        $itemId         = $this->getItemId();
        try{
            $DataMysql  = new DataMysql($this->DbConf, 'MYSQL_P_'.$itemId);
            $DataMysql->connect();
        }catch(MysqlConnectException $MysqlConnectException){
            Logs::exception($MysqlConnectException->getMessageLog(), $MysqlConnectException->getLine(), $MysqlConnectException->getFile(), '');
            return false;
        }
        $PoolItem       = new PoolItem($DataMysql, $this->getItemId());
        if($isUse) $PoolItem->used();
        $DataMysql->initPool($this, $PoolItem);
        return $PoolItem;
    }

    /**
     * @param PoolItem $PoolItem
     * @return bool
     * recycleResult
     */
    final protected function recycleResult(PoolItem $PoolItem):bool
    {
        $DataMysql          = $PoolItem->getPoolObject();
        if($DataMysql instanceof DataMysql && !$PoolItem->isUse()){
            return $DataMysql->close();
        }
        return false;
    }

    /**
     * @param PoolItem $PoolItem
     * @return bool
     * checkResult
     */
    final protected function checkResult(PoolItem $PoolItem):bool
    {
        $DataMysql          = $PoolItem->getPoolObject();
        if($DataMysql instanceof DataMysql && !$PoolItem->isUse()){
            return $DataMysql->isConnected();
        }
        return false;
    }

    /**
     * @param bool $isAutoFree
     * @return DataMysql
     * @throws PoolItemMysqlException
     * getDataMysql
     */
    final public function getDataMysql(bool $isAutoFree):DataMysql
    {
        try{
            $DataMysql      = $this->getPoolItem($isAutoFree)->getPoolObject();
            if($DataMysql instanceof DataMysql) return $DataMysql;
        }catch(PoolItemException $PoolItemException){
            Logs::exception($PoolItemException->getMessageLog(), $PoolItemException->getLine(), $PoolItemException->getFile(), '');
        }
        throw new PoolItemMysqlException(CommJson::encodeArray(['msg' => 'DataMysql get failed']), -1);
    }
}